package com.afdor.rws.event.autoconfigure;

import com.afdor.rws.core.extension.ExtensionLoader;
import com.afdor.rws.event.Event;
import com.afdor.rws.event.EventBus;
import com.afdor.rws.event.EventPersistenceManager;
import com.afdor.rws.event.EventSource;
import com.afdor.rws.event.EventSourceManager;
import com.afdor.rws.event.channel.ChannelProvider;
import com.afdor.rws.event.config.EventConfig;
import com.afdor.rws.event.config.EventConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;

/**
 * event-driven框架spring boot启动配置类
 *
 * @author 悭梵
 * @date Created in 2018-08-22 15:21
 */
@Configuration
public class EventDrivenConfigation {

    /**
     * 事件相关配置初始化
     *
     * @param environment
     * @return
     */
    @Bean
    @Lazy
    public EventConfig globalEventConfig(Environment environment) {
        EventConfig eventConfig = new EventConfig();
        // 事件ID 生成策略，扩展点名称。默认uuid，由IdGeneratorStrategy.SPI("uuid")负责激活
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_STRATEGY_NAME_ID);
        // 事件时间获取策略，扩展点名称。默认local_timestamp，由TimestampStrategy.SPI("local_timestamp")负责激活
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_STRATEGY_NAME_TIMESTAMP);
        // 自定义事件总线扩展点名称。默认default，有EventBus.SPI("default")负责激活
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_EVENT_BUS_NAME);
        // 事件源，扩展点名称。默认default，由EventSource.SPI("default")负责激活默认值
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_SOURCE_NAME);
        // 事件源管理器，扩展点名称。默认default，由EventSourceManager.SPI("default")负责激活默认值
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_SOURCE_MANAGER_NAME);
        // 事件持久化管理器，扩展点名称。默认default，由EventPersistenceManager.SPI("default")负责激活默认值
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_PERSISTENCE_MANAGER_NAME);
        // 聚合根事件是否发送，默认不发送
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_EVENT_BUS_IS_SEND_AGGREGATION_ROOT_EVENT);
        // 事件总线中事物ID 生成策略，扩展点名称。默认uuid，由IdGeneratorStrategy.SPI("uuid")负责激活
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_EVENT_BUS_TRANSACTION_ID);
        // 事件持久化处理间隔事件，单位毫秒，默认1000
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_PERSISTENCE_PERIOD);
        // 事件持久化一次处理的事件量，默认50
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_PERSISTENCE_BATCH_SIZE);
        // 事件序列化扩展点名称，必填。各种实现方式，存在默认值不一样情况
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CHANNEL_SERIALIZATION_NAME);
        // 事件传递通道扩展点名称，必填。各种实现方式，默认值不一样
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CHANNEL_NAME);
        // 生产者扩展点名称，必填。各种实现方式，存在默认值不一样情况
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_PRODUCER_NAME);
        // 采用副本事件拦截链进行拦截，默认：false。在拦截链比较固定的情况下，推荐false，若拦截链经常动态变化，推荐true。
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_INTERCEPT_CHAIN_CLONE);
        // 生产者事件拦截链的扩展点名称，允许为空。默认default，由EventInterceptChain.SPI("default")负责激活
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_PRODUCER_INTERCEPT_CHAIN_NAME);
        // 消费者事件拦截链的扩展点名称，允许为空。默认default，由EventInterceptChain.SPI("default")负责激活
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_INTERCEPT_CHAIN_NAME);
        // 消费者扩展点名称，必填。各种实现方式，存在默认值不一样情况
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_NAME);
        // 最大重试次数。默认3,但各种实现方式，存在默认值不一样情况
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_MAX_RETRY_NUM);
        // 消费者事件重试策略扩展点名称。默认default，由EventRetryStrategy.SPI("default")负责激活。该默认值只做持久化，未做重试，谨慎使用
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_RETRY_NAME);
        // 消费者监听事件处理间隔事件，单位毫秒，默认1000
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_HANDLER_PERIOD);
        // 获取消息阻塞时间。默认-1，小于等于0时，不调用阻塞获取方法。不推荐阻塞获取。
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_GET_MESSAGE_TIMEOUT);
        // 一次获取消息的数量，默认：50，各种实现方式，存在默认值不一样情况
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_GET_MESSAGE_BATCH_SIZE);
        // 默认广播事件处理器名称，允许为空。
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_HANDLER_DEFAULT_BROADCAST_NAME);
        // 默认骨架事件处理器名称，允许为空。
        setProperty(environment, eventConfig, EventConfigUtils.EVENT_CONSUMER_HANDLER_DEFAULT_AGGREGATION_ROOT_NAME);
        // 全局配置
        EventConfigUtils.setGlobalConfig(eventConfig);
        return eventConfig;
    }

    private void setProperty(Environment environment, EventConfig eventConfig, String eventStrategyNameId) {
        String value = environment.getProperty(eventStrategyNameId);
        if (value != null) {
            eventConfig.setProperty(eventStrategyNameId, value);
        }
    }

    /**
     * 注册事件通道
     *
     * @return
     */
    @Bean
    @Lazy
    @DependsOn("globalEventConfig")
    public ChannelProvider defaultChannelProvider() {
        return ExtensionLoader
                .getInstance(ChannelProvider.class)
                .getExtensionOrDefault(EventConfigUtils.getProperty(EventConfigUtils.EVENT_CHANNEL_NAME))
                .init();
    }

    /**
     * 初始化聚合根事件处理配置信息
     *
     * @return
     */
    @Bean
    @Lazy
    @DependsOn("defaultChannelProvider")
    public EventSource rootEventSource() {
        return ExtensionLoader
                .getInstance(EventSource.class)
                .newExtensionOrDefault(EventConfigUtils.getProperty(EventConfigUtils.EVENT_SOURCE_NAME))
                .setEventSourceName(Event.Type.AGGREGATION_ROOT.getDefaultSourceName())
                .setChannelProvider(defaultChannelProvider());
    }

    /**
     * 初始化聚合根事件处理配置信息
     *
     * @return
     */
    @Bean
    @Lazy
    @DependsOn("defaultChannelProvider")
    public EventSource broadcastEventSource() {
        return ExtensionLoader
                .getInstance(EventSource.class)
                .newExtensionOrDefault(EventConfigUtils.getProperty(EventConfigUtils.EVENT_SOURCE_NAME))
                .setEventSourceName(Event.Type.BROADCAST.getDefaultSourceName())
                .setChannelProvider(defaultChannelProvider());
    }

    /**
     * 初始化事件源管理器
     *
     * @return
     */
    @Bean
    @Lazy
    @DependsOn("rootEventSource")
    public EventSourceManager defaultEventSourceManager() {
        return ExtensionLoader
                .getInstance(EventSourceManager.class)
                .getExtensionOrDefault(EventConfigUtils.getProperty(EventConfigUtils.EVENT_SOURCE_MANAGER_NAME))
                .init()
                .addEventSource(rootEventSource())
                .addEventSource(broadcastEventSource());
    }

    /**
     * 初始化持久化管理器
     *
     * @return
     */
    @Bean
    @Lazy
    @DependsOn("globalEventConfig")
    public EventPersistenceManager defaultEventPersistenceManager() {
        return ExtensionLoader
                .getInstance(EventPersistenceManager.class)
                .getExtensionOrDefault(EventConfigUtils.getProperty(EventConfigUtils.EVENT_PERSISTENCE_MANAGER_NAME))
                .init();
    }

    /**
     * 初始化事件总线
     *
     * @return
     */
    @Bean
    @Lazy
    @DependsOn({"defaultEventSourceManager", "defaultEventPersistenceManager"})
    public EventBus defaultEventBus() {
        return ExtensionLoader
                .getInstance(EventBus.class)
                .getExtensionOrDefault(EventConfigUtils.getProperty(EventConfigUtils.EVENT_EVENT_BUS_NAME))
                .setEventSourceManager(defaultEventSourceManager())
                .setEventPersistenceManager(defaultEventPersistenceManager())
                .init();
    }
}
